package com.scfire.pay

import java.text.DateFormat
import java.text.SimpleDateFormat

import org.springframework.transaction.annotation.*

import com.mongodb.BasicDBObject
import com.mongodb.DBCollection
import com.mongodb.DBObject
import com.scfire.fund.FDonate
import com.scfire.fund.FRuler
import com.scfire.fund.FundPool
import com.scfire.project.Donate
import com.scfire.project.Project
import com.scfire.project.SubProject
import com.scfire.security.Member
import com.scfire.util.SCFIREConstants
import com.scfire.weixin.WeiXinConstants

class PayService {
	private final $lock = new Object[0]
	
	public static Map forLock = new HashMap();
	
	public static Map forLockfundPool = new HashMap();
	
	def deviceInfoService
	def weiXinService
	def springSecurityService
	def alipayService
	def SystemMessageService
	def feedBackService
	
	def mongo
	def grailsApplication
	
	static transactional = true
	/**
	 * 微信付款成功回调函数  --- 紧急优化解决事务问题
	 * @param null
	 * @return null
	 *
	 * **/
	@Transactional(propagation = Propagation.REQUIRED)
	def weixinCallBack(String memberId,
				 String projectId,
				 float donate_fee,
				 float operate_fee,
				 String subprojectid,
				 String total_fee,
				 String out_trade_no,
				 String openid,
				 String transaction_id,
				 boolean checked,
				 String attach,
				 String donateNoNew){
				 boolean weixinflag = false
				 def donateurlTemp;
				 def projectTemp
				if(forLock.get(projectId)==null){
					forLock.put(projectId, new Object[0])
				} 
	 synchronized(forLock.get(projectId)) {
		 
		 Thread t = Thread.currentThread()
		 println "---------Start time: " + new Date()+ "---------"+" thread id"+t.getName()
						 
		try{
			//判断是否已经有捐赠记录
			Donate donate = Donate.findByOut_trade_no(out_trade_no)
			if(donate){
				return true
			}
			
			Member member = Member.findById(memberId)
			Project project = Project.findById(projectId)
			String donateurl = ""
			SubProject subproject
			//加载mongodb
			def db = mongo.getDB(grailsApplication.config.grails.mongo.databaseName)
			
			//若是一起捐 则保存信息到subproject
			if(!subprojectid.equals("-1")){
				subproject = SubProject.findById(subprojectid)
				subproject.subrest -= Float.valueOf(donate_fee)
				subproject.subdonate += Float.valueOf(donate_fee)
				def subprogress = 100-(subproject.subrest/subproject.subamount)*100
				
				
				BigDecimal   b  =   new BigDecimal(subprogress);
				subproject.subprogress =  b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
				
				//4.金额计算，subProject rest计算，
				if(subproject.subrest <= 0){
					subproject.subrest = 0
					subproject.subprogress = 100
				}
				subproject.subdonateSize++
				
				FRuler fRuler = FRuler.findByProjectAndStatus(project,"true")
				int fdonatemoney = 0
				float regular = 0
				if(fRuler != null){
					FundPool fundPool = fRuler.fundPool
					BigDecimal bd = new BigDecimal(Float.toString(donate_fee))
					bd=bd*100;
					int donatemoney = bd.intValue();
					int bandfund = fRuler.bandfund
					int donatefund = fRuler.donatefund
					String fRegular = fRuler.regular
					String[] fRs = fRegular.split(":")
					regular = (Float.valueOf(fRs[1])/Float.valueOf(fRs[0])) //保留两位
					
					//计算可用金额 = 绑定配捐金额-实际已配捐金额
					int restfund = bandfund - donatefund
					if(restfund > 0){
						//可用金额根据配捐规则大于此次要配捐的金额,则进行配捐
						if(restfund >= donatemoney*regular){
							fdonatemoney = donatemoney*regular
						}else{
							//最后剩余的全部进行配捐
							fdonatemoney = restfund
						}
					}
				}
				subproject.subfdonate+=fdonatemoney
				DBCollection projectCollection = db.getCollection("subProject")
				DBObject queryCondition= new BasicDBObject()
				queryCondition.put("_id",Integer.valueOf(subprojectid))
				BasicDBObject updateParameter =new BasicDBObject().append("\$set",new BasicDBObject().append("subrest", subproject.subrest)
					.append("subdonate", subproject.subdonate)
					.append("subprogress", subproject.subprogress)
					.append("subdonateSize", subproject.subdonateSize)
					.append("subfdonate", subproject.subfdonate)
					)
				
				projectCollection.update(queryCondition, updateParameter,true,true)		
				//subproject.save flush : true
				println "---------save subproject time: " + new Date()+ "---------"+" thread id"+t.getName()
				
			}
			
			
			long timestap = System.currentTimeMillis()/1000
			
			//捐赠信息
			donate = new Donate()
			donate.donateNo = UUID.randomUUID()
			donate.donateNoNew = donateNoNew
			donate.money = Float.valueOf(total_fee)/100
	
			donate.donate_fee = donate_fee
			donate.operate_fee = operate_fee
			donate.operate_fee_status = checked
	
			donate.date = new Date()
			donate.status = true
			donate.member = member.id
			donate.project = project.id
			//若是一起捐 保存捐赠信息到donate
			if(!subprojectid.equals("-1")) donate.subProject = subproject.id
			donate.out_trade_no = out_trade_no
			donate.openid = openid
			donate.transaction_id = transaction_id
			donate.attach = attach
			donate.type = "微信支付"
			//donate.save flush : true
			
			DBCollection projectCollections = db.getCollection("donate")
			BasicDBObject doc_info = new BasicDBObject();
			
			doc_info.put("donateNo", donate?.donateNo);
			doc_info.put("donateNoNew", donate?.donateNoNew);
			doc_info.put("money",  String.valueOf(donate.money));
			doc_info.put("donate_fee", String.valueOf(donate.donate_fee));
			doc_info.put("operate_fee", String.valueOf(donate.operate_fee));
			doc_info.put("operate_fee_status", donate?.operate_fee_status);
			doc_info.put("date", donate.date);
			doc_info.put("status", donate.status);
			doc_info.put("member", member?.id);
			doc_info.put("project", project?.id);
			if(!subprojectid.equals("-1")) {
				doc_info.put("subProject", subproject.id);
			}
			doc_info.put("out_trade_no", donate.out_trade_no);
			doc_info.put("openid", donate.openid);
			doc_info.put("transaction_id", donate.transaction_id);
			doc_info.put("attach", donate.attach);
			doc_info.put("type", donate.type);
			Donate d= Donate.last()
			doc_info.put("_id", d.id+1);
			try {
				projectCollections.insert(doc_info);
			} catch (Exception e) {
			Donate d1= Donate.last()
			println "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" +d1.id+1
			doc_info.put("_id", d1.id+1);
			projectCollections.insert(doc_info);
			}
			println "---------save donate time: " + new Date()+ "---------"+" thread id"+t.getName()
			
			//手动查找donate.id
			Donate donate2 = Donate.findByOut_trade_no(out_trade_no)
			donateurl = SCFIREConstants.PROJECT_DONATE_ELECTRONIC_INFO+donate2.id
			//donateurl = "http://www.huodui.org/scfire/user/modifyMoblie"
			
			/*******************资金池配捐信息处理START*************************/
			//配捐信息获取
			FRuler fRuler = FRuler.findByProjectAndStatus(project,"true")
			//配捐标识
			boolean fdonateFlag = false
			//配捐金额
			int fdonatemoney = 0
			
			float regular = 0
			//如果项目有绑定资金池
			if(fRuler != null){
				FundPool fundPool = fRuler.fundPool
				if(forLockfundPool.get(String.valueOf(fundPool.id))==null){
					forLockfundPool.put(String.valueOf(fundPool.id), new Object[0])
				}
				synchronized(forLockfundPool.get(String.valueOf(fundPool.id))){
				BigDecimal bd = new BigDecimal(Float.toString(donate_fee))
				bd=bd*100;
				int donatemoney = bd.intValue();
				println "-----1----"+donatemoney+"---------"
				int bandfund = fRuler.bandfund
				int donatefund = fRuler.donatefund
				String fRegular = fRuler.regular
				String[] fRs = fRegular.split(":")									
				regular = (Float.valueOf(fRs[1])/Float.valueOf(fRs[0])) //保留两位				
				
				//计算可用金额 = 绑定配捐金额-实际已配捐金额
				int restfund = bandfund - donatefund			
				if(restfund > 0){
					//可用金额根据配捐规则大于此次要配捐的金额,则进行配捐
					if(restfund >= donatemoney*regular){
						fdonatemoney = donatemoney*regular
						fRuler.donatefund += fdonatemoney
					}else{
						//最后剩余的全部进行配捐
						fdonatemoney = restfund
						fRuler.donatefund = bandfund	
					}
					
					println "---2------"+fdonatemoney+"---------"
					//添加配捐信息
					Donate donate1 = Donate.findByOut_trade_no(out_trade_no)
					FDonate fDonate = new FDonate()
					fDonate.donate_fee = fdonatemoney
					fDonate.status = "true"
					fDonate.date = new Date()
					fDonate.fundPool = fundPool.id
					fDonate.project = project.id
					fDonate.member = member.id
					fDonate.donate = donate1.id	
					
					//fDonate.save flush:true
					
					
					DBCollection projectCollections2 = db.getCollection("FDonate")
					BasicDBObject doc_info2 = new BasicDBObject();
					
					doc_info2.put("donate_fee", fDonate.donate_fee);
					doc_info2.put("status",fDonate.status);
					doc_info2.put("date", fDonate.date);
					doc_info2.put("fundPool",fundPool?.id);
					doc_info2.put("project", project?.id);
					doc_info2.put("member", member?.id);
					doc_info2.put("donate",donate1?.id);
					doc_info2.put("version",0);
					FDonate fd= FDonate.last()
					doc_info2.put("_id", fd.id+1);
					try {
						projectCollections2.insert(doc_info2);
					} catch (Exception e) {
						FDonate fd1= FDonate.last()
						doc_info2.put("_id", fd1.id+1);
						projectCollections2.insert(doc_info2);
					}
					println "---------fDonate save " + new Date()+ "---------"+" thread id"+t.getName()
					//更新配捐规则中实际配捐金额信息
					fRuler.save flush:true
					println "---------fRuler save " + new Date()+ "---------"+" thread id"+t.getName()
					//更新资金池中实际已经配捐金额信息
					fundPool.donateActual += fdonatemoney
					DBCollection projectCollection = db.getCollection("fundPool")
					DBObject queryCondition= new BasicDBObject()
					queryCondition.put("_id",fundPool.id)
					BasicDBObject updateParameter =new BasicDBObject().append("\$set",new BasicDBObject().append("donateActual", fundPool.donateActual))
					projectCollection.update(queryCondition, updateParameter,true,true)
					//fundPool.save flush:true
					println "---------fundPool save " + new Date()+ "---------"+" thread id"+t.getName()
					fdonateFlag = true
				}
			 }	
			}
			/*******************资金池配捐信息处理END*************************/
			weixinflag = true;
			donateurlTemp= donateurl
			projectTemp = project?.name
			//微信发送模板支付凭证
			/*boolean proof = weiXinService.templet(WeiXinConstants.donate_id , member?.openid , donateurl , project?.name , Float.valueOf(total_fee)/100+"" , member?.nickname)
			println "send stats : "+ proof*/
			//rest修改为donate_fee  不包含平台管理费
			//判断是否有配捐信息
			/*if(fdonateFlag){
				project.rest -= (Float.valueOf(donate_fee)+Float.valueOf(fdonatemoney)/100)
				project.fDonateSize++;
				project.realAmount+=(Float.valueOf(donate_fee)+Float.valueOf(fdonatemoney)/100)
			}else{
				project.rest -= Float.valueOf(donate_fee)
				project.realAmount+=Float.valueOf(donate_fee)
			}
			project.progress = 100-(project.rest/project.amount)*100			
			
			//将剩余的钱捐入某个永久项目
			if(project.rest <= 0){
				//TODO
				project.rest = 0
				project.progress = 100
				project.verified = SCFIREConstants.PROJECT_APPROVE_EXECUTE
				//保存系统通知消息
				SystemMessageService.sendSysMessage(SCFIREConstants.SYSTEM_MESSAGE_PROJECT_FUND_SUCCESS_FRONT+project.name+SCFIREConstants.SYSTEM_MESSAGE_PROJECT_FUND_SUCCESS_BACK, project.member);
	
				//筹款成功：推送该项目所有捐赠人，提示用户项目筹款成功，已进入执行阶段，点击详情持续关注项目进展
				Map<String, String> donateUsersOpenid = new HashMap<String, String>()
				Date  date = new Date();
				DateFormat fmt =new SimpleDateFormat("yyyy-MM-dd HH:mm");
				Iterator its = project?.donates?.iterator()
				while(its.hasNext()){
					Donate temp = (Donate)its.next()
					if(temp?.member?.openid){
						donateUsersOpenid.put(temp?.member?.openid , temp?.member?.openid)
					}
				}
				weiXinService.sendMassTemplateStatus(WeiXinConstants.service_id, donateUsersOpenid, project?.name+"项目已筹满，您支持的此项目已筹满，我们将尽快支付善款给项目发起人，点击详情持续关注项目最新进展。", fmt.format(date), "项目筹款", "筹款", "成功" , WeiXinConstants.server+"/project/projectDetail?projectid="+project?.id)	
	
	
				//筹款成功：推送该项目发起人，提示用户项目筹款成功，会在5个工作日内打款到您的账上，请点击详情确认收款信息是否准确
				if(project?.member?.openid){
					weiXinService.template_status(WeiXinConstants.service_id, project?.member?.openid, project?.name+"项目已筹满，我们会在5个工作日内支付善款到您的银行卡上，点击详情查看并确认收款银行账号是否准确。", fmt.format(date), "项目筹款", "筹款", "成功" , WeiXinConstants.server+"/user/userAuthInfo")
				}
				
				//筹款成功：发布项目动态，“项目筹款成功”
				feedBackService.insertFeedBack(SCFIREConstants.PROJECT_FEEDBACK_PASS_F+project.name+SCFIREConstants.PROJECT_FEEDBACK_PASS_E, project.id+"")
			}
			
			//捐赠的用户去重
			Set donateMember = new HashSet<>()
			donateMember.add(member.id)
			for(Donate d:project.donates){
			def m = d.member.id
			donateMember.add(m)
			}
			project.donateNum = donateMember.size()
		   //捐赠的用户数累加，按照捐一次累积一次，不做member的去重
		   project.donateNum = project.donateNum+1
		 
		   
		   //2016年5月更新project表结构		   
		   
		   project.save flush : true*/
			DBCollection projectCollection = db.getCollection("project")
			DBObject queryCondition= new BasicDBObject()
			queryCondition.put("_id",Integer.valueOf(projectId))
			
			float rest = project.rest
			int fDonateSize = project.fDonateSize
			float realAmount = project.realAmount
			float progress = project.progress
			String verified = project.verified
			int donateNum = project.donateNum
			
			if(fdonateFlag){
				project.rest = project.rest - (Float.valueOf(donate_fee)+Float.valueOf(fdonatemoney)/100)
				project.fDonateSize = project.fDonateSize++
				project.realAmount = project.realAmount + (Float.valueOf(donate_fee)+Float.valueOf(fdonatemoney)/100)
			}else{
				project.rest = project.rest - Float.valueOf(donate_fee)
				project.realAmount = project.realAmount+Float.valueOf(donate_fee)
			}
			
			
			
			progress = 100-(project.rest/project.amount)*100
			BigDecimal   b  =   new BigDecimal(progress);
			project.progress =  b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
			
			//将剩余的钱捐入某个永久项目
			if(project.rest <= 0){
				//TODO
				project.rest = 0
				project.progress = 100
				project.verified = SCFIREConstants.PROJECT_APPROVE_EXECUTE
				//保存系统通知消息
				SystemMessageService.sendSysMessage(SCFIREConstants.SYSTEM_MESSAGE_PROJECT_FUND_SUCCESS_FRONT+project.name+SCFIREConstants.SYSTEM_MESSAGE_PROJECT_FUND_SUCCESS_BACK, project.member);
	
				//筹款成功：推送该项目所有捐赠人，提示用户项目筹款成功，已进入执行阶段，点击详情持续关注项目进展
				Map<String, String> donateUsersOpenid = new HashMap<String, String>()
				Date  date = new Date();
				DateFormat fmt =new SimpleDateFormat("yyyy-MM-dd HH:mm");
				
				
				def Criteriaproject = Donate.createCriteria()
				def dfc = {
					eq("project",project.id)
					order("date", "desc")
					projections {
						distinct ("member")
						   }
				}
				def members = Criteriaproject.listDistinct(dfc);
				for(int id:members){
					def member2 = Member.findById(id)
					donateUsersOpenid.put(member2?.openid , member2?.openid)
				}

				weiXinService.sendMassTemplateStatus(WeiXinConstants.service_id, donateUsersOpenid, project?.name+"项目已筹满，您支持的此项目已筹满，我们将尽快支付善款给项目发起人，点击详情持续关注项目最新进展。", fmt.format(date), "项目筹款", "筹款", "成功" , WeiXinConstants.server+"/project/projectDetail?projectid="+project?.id)
	
	
				//筹款成功：推送该项目发起人，提示用户项目筹款成功，会在5个工作日内打款到您的账上，请点击详情确认收款信息是否准确
				def projectmember
				if(project?.member){
					projectmember= Member.findById(project?.member)
					weiXinService.template_status(WeiXinConstants.service_id, projectmember?.openid, project?.name+"项目已筹满，我们会在5个工作日内支付善款到您的银行卡上，点击详情查看并确认收款银行账号是否准确。", fmt.format(date), "项目筹款", "筹款", "成功" , WeiXinConstants.server+"/user/userAuthInfo")
				}
				
				//筹款成功：发布项目动态，“项目筹款成功”
				feedBackService.insertFeedBack(SCFIREConstants.PROJECT_FEEDBACK_PASS_F+project.name+SCFIREConstants.SYSTEM_MESSAGE_PROJECT_FUND_SUCCESS_BACK, project.id+"","execute")
				
				
				def adminMembers = Member.findAllByPushFlag(true);
				Map<String, String> donateUsersOpenid2 = new HashMap<String, String>()
				for(Member member2:adminMembers){
					donateUsersOpenid2.put(member2?.openid , member2?.nickname)
				}
				weiXinService.sendMassTemplateStatus2(WeiXinConstants.service_id, donateUsersOpenid2, "您好,"+projectmember.nickname+"的项目《"+project.name+"》，已经筹满！", fmt.format(date), "项目筹满", "项目筹满", "成功" , WeiXinConstants.server+"/project/projectDetail?projectid="+project?.id)
			}
			
			/*//捐赠的用户去重
			Set donateMember = new HashSet<>()
			donateMember.add(member.id)
			for(Donate d:project.donates){
			def m = d.member.id
			donateMember.add(m)
			}
			project.donateNum = donateMember.size()*/
		   //捐赠的用户数累加，按照捐一次累积一次，不做member的去重
		    project.donateNum++
		   BasicDBObject updateParameter =new BasicDBObject().append("\$set",new BasicDBObject().append("rest", project.rest)
																.append("fDonateSize", project.fDonateSize)
																.append("realAmount", project.realAmount)
																.append("progress", project.progress)
																.append("verified", project.verified)
																.append("donateNum", project.donateNum)
																)
															
		  projectCollection.update(queryCondition, updateParameter,true,true)
		 
		   
		   //2016年5月更新project表结构		   
		   //project.save flush : true
		   
		}catch(Exception e){
			println "weixincallBack catch exception "+e.getMessage()
			return false
		}
		println "---------End time: " + new Date()+ "---------"+" thread id"+t.getName()
		/*return true	*/	
	 }
	 
	 if(weixinflag){
		 Thread t = Thread.currentThread()
		 println "---------start time: " + new Date()+ "---------"+" thread id："+t.getName()
		 Member member = Member.findById(memberId)
		 boolean proof = weiXinService.templet(WeiXinConstants.donate_id , member?.openid , donateurlTemp , projectTemp , Float.valueOf(total_fee)/100+"" , member?.nickname)
		 println "send stats weixin : "+ proof
		 donateurlTemp=""
		 projectTemp=""
		 weixinflag = false
	 }
	 return true
	}
	
				 
	 /**
	  * 支付宝付款成功回调函数  --- 紧急优化解决事务问题
	  * @param null
	  * @return null
	  *
	  * **/
	 @Transactional(propagation = Propagation.REQUIRED)
	 def alipayCallBack(String memberid,
				  String projectid,
				  String out_trade_no,
				  String trade_no,
				  String trade_status,
				  String subprojectid,
				  String total_fee,
				  float donate_fee,
				  float operate_fee,
				  boolean checked,
				  String checked_string){
				  boolean aipayFlag = false
				  def donateurlTemp;
				  def projectTemp
				  if(forLock.get(projectid)==null){
					  forLock.put(projectid, new Object[0])
				  }
	  synchronized(forLock.get(projectid)) {
		  Thread t = Thread.currentThread()
		  println "---------Start time: " + new Date()+ "---------"+" thread id"+t.getName()
		  
		try{
				
			Donate donate = Donate.findByOut_trade_no(out_trade_no)
			if(donate){
				return true
			}
			
			def db = mongo.getDB(grailsApplication.config.grails.mongo.databaseName)
			Member member = Member.findById(memberid)
			Project project = Project.findById(projectid)
			SubProject subproject
			
			//2.若是一起捐 则保存信息到subproject
			if(!subprojectid.equals("-1")){
					subproject = SubProject.findById(subprojectid)
					subproject.subrest -= Float.valueOf(donate_fee)
					subproject.subdonate += Float.valueOf(donate_fee)
					float subprogress = 100-(subproject.subrest/subproject.subamount)*100
					BigDecimal   b  =   new BigDecimal(subprogress);
					subproject.subprogress=  b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
					//4.金额计算，subProject rest计算，
					if(subproject.subrest <= 0){
						//TODO
						subproject.subrest = 0
						subproject.subprogress = 100
					}
					subproject.subdonateSize++
					
					FRuler fRuler = FRuler.findByProjectAndStatus(project,"true")
					int fdonatemoney = 0
					float regular = 0
					if(fRuler != null){
						FundPool fundPool = fRuler.fundPool
						BigDecimal bd = new BigDecimal(Float.toString(donate_fee))
						bd=bd*100;
						int donatemoney = bd.intValue();
						int bandfund = fRuler.bandfund
						int donatefund = fRuler.donatefund
						String fRegular = fRuler.regular
						String[] fRs = fRegular.split(":")
						regular = (Float.valueOf(fRs[1])/Float.valueOf(fRs[0])) //保留两位
						
						//计算可用金额 = 绑定配捐金额-实际已配捐金额
						int restfund = bandfund - donatefund
						if(restfund > 0){
							//可用金额根据配捐规则大于此次要配捐的金额,则进行配捐
							if(restfund >= donatemoney*regular){
								fdonatemoney = donatemoney*regular
							}else{
								//最后剩余的全部进行配捐
								fdonatemoney = restfund
							}
						}
					}
					subproject.subfdonate+=fdonatemoney
					
					DBCollection projectCollection = db.getCollection("subProject")
					DBObject queryCondition= new BasicDBObject()
					queryCondition.put("_id",Integer.valueOf(subprojectid))
					BasicDBObject updateParameter =new BasicDBObject().append("\$set",new BasicDBObject().append("subrest", subproject.subrest)
						.append("subdonate", subproject.subdonate)
						.append("subprogress", subproject.subprogress)
						.append("subdonateSize", subproject.subdonateSize)
						.append("subfdonate", subproject.subfdonate)
						)
					
					projectCollection.update(queryCondition, updateParameter,true,true)
					
					
					subproject.save flush : true
			}
			
			println "增加捐赠记录"
			long timestap = System.currentTimeMillis()/1000
			//捐赠信息
			donate = new Donate()
			donate.donateNo = UUID.randomUUID()
			donate.donateNoNew = project.id+""+member.id+""+timestap
			donate.money = Float.valueOf(total_fee)
	
			//记录支付金额信息
			donate.donate_fee = donate_fee
			donate.operate_fee = operate_fee
			donate.operate_fee_status = checked
			donate.date = new Date()
			donate.status = true
			donate.member = member.id
			donate.project = project.id
			//若是一起捐 保存捐赠信息到donate
			if(!subprojectid.equals("-1")) donate.subProject = subproject.id
			donate.out_trade_no = out_trade_no
			donate.openid = member?.openid
			donate.transaction_id = ""
			String attach =     "{\"p\":\""+projectid+"\",\"m\":\""+memberid+"\","+
			"\"c\":\""+checked_string+"\",\"df\":\""+donate_fee+"\","+
			"\"of\":\""+operate_fee+"\",\"s\":\""+subprojectid+"\",\"dn\":\""+donate.donateNoNew+"\"}";
			donate.attach = attach
			donate.type = "支付宝支付"
			//donate.save flush : true
			DBCollection projectCollections = db.getCollection("donate")
			BasicDBObject doc_info = new BasicDBObject();
			doc_info.put("donateNo", donate?.donateNo);
			doc_info.put("donateNoNew", donate?.donateNoNew);
			doc_info.put("money",  String.valueOf(donate.money));
			doc_info.put("donate_fee", String.valueOf(donate.donate_fee));
			doc_info.put("operate_fee", String.valueOf(donate.operate_fee));
			doc_info.put("operate_fee_status", donate?.operate_fee_status);
			doc_info.put("date", donate.date);
			doc_info.put("status", donate.status);
			doc_info.put("member", member?.id);
			doc_info.put("project", project.id);
			if(!subprojectid.equals("-1")) {
				doc_info.put("subProject", subproject.id);
			}
			doc_info.put("out_trade_no", donate.out_trade_no);
			doc_info.put("openid", donate?.openid);
			doc_info.put("transaction_id", donate.transaction_id);
			doc_info.put("attach", donate.attach);
			doc_info.put("type", donate.type);
			Donate d= Donate.last()
			doc_info.put("_id", d.id+1);
			try {				
				projectCollections.insert(doc_info);
			} catch (Exception e) {
			Donate d1= Donate.last()
			println "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" +d1.id+1
			
			doc_info.put("_id", d1.id+1);
			projectCollections.insert(doc_info);
			}
			
			println "---------donate save time: " + new Date()+ "---------"+" thread id"+t.getName()
			String donateurl = "";
			Donate donate2 = Donate.findByOut_trade_no(out_trade_no)
			donateurl = SCFIREConstants.PROJECT_DONATE_ELECTRONIC_INFO+donate2?.id
			//donateurl = "http://www.huodui.org/scfire/user/modifyMoblie"
			
			/*******************资金池配捐信息处理START*************************/
			//配捐信息获取
			FRuler fRuler = FRuler.findByProjectAndStatus(project,"true")
			//配捐标识
			boolean fdonateFlag = false
			//配捐金额
			int fdonatemoney = 0
			float regular = 0
			//如果项目有绑定资金池
			if(fRuler != null){
				FundPool fundPool = fRuler.fundPool
				if(forLockfundPool.get(String.valueOf(fundPool.id))==null){
					forLockfundPool.put(String.valueOf(fundPool.id), new Object[0])
				}
				synchronized(forLockfundPool.get(String.valueOf(fundPool.id))){
				BigDecimal bd = new BigDecimal(Float.toString(donate_fee))
				bd=bd*100;
				int donatemoney = bd.intValue();
				int bandfund = fRuler.bandfund
				int donatefund = fRuler.donatefund
				String fRegular = fRuler.regular
				String[] fRs = fRegular.split(":")									
				regular = (Float.valueOf(fRs[1])/Float.valueOf(fRs[0])) //保留两位
				
				//计算可用金额 = 绑定配捐金额-实际已配捐金额
				int restfund = bandfund - donatefund			
				if(restfund > 0){
					//可用金额根据配捐规则大于此次要配捐的金额,则进行配捐
					if(restfund >= donatemoney*regular){
						fdonatemoney = donatemoney*regular
						fRuler.donatefund += fdonatemoney
					}else{
						//最后剩余的全部进行配捐
						fdonatemoney = restfund
						fRuler.donatefund = bandfund	
					}
					//添加配捐信息
					Donate donate1 = Donate.findByOut_trade_no(out_trade_no)
					FDonate fDonate = new FDonate()
					fDonate.donate_fee = fdonatemoney
					fDonate.status = "true"
					fDonate.date = new Date()
					fDonate.fundPool = fundPool.id
					fDonate.project = project.id
					fDonate.member = member.id
					fDonate.donate = donate1.id		
					//fDonate.save flush:true
					
					
					
					DBCollection projectCollections2 = db.getCollection("FDonate")
					BasicDBObject doc_info2 = new BasicDBObject();
					
					doc_info2.put("donate_fee", fDonate.donate_fee);
					doc_info2.put("status",fDonate.status);
					doc_info2.put("date", fDonate.date);
					doc_info2.put("fundPool",fundPool?.id);
					doc_info2.put("project", project?.id);
					doc_info2.put("member", member?.id);
					doc_info2.put("donate",donate1?.id);
					doc_info2.put("version",0);
					FDonate fd= FDonate.last()
					doc_info2.put("_id", fd.id+1);
					try {
						projectCollections2.insert(doc_info2);
					} catch (Exception e) {
						FDonate fd1= FDonate.last()
						doc_info2.put("_id", fd1.id+1);
						projectCollections2.insert(doc_info2);
					}
					
					//更新配捐规则中实际配捐金额信息
					fRuler.save flush:true
					
					//更新资金池中实际已经配捐金额信息
					fundPool.donateActual += fdonatemoney
					//fundPool.save flush:true
					
					
					DBCollection projectCollection = db.getCollection("fundPool")
					DBObject queryCondition= new BasicDBObject()
					queryCondition.put("_id",fundPool.id)
					BasicDBObject updateParameter =new BasicDBObject().append("\$set",new BasicDBObject().append("donateActual", fundPool.donateActual))
					projectCollection.update(queryCondition, updateParameter,true,true)
					
					fdonateFlag = true
					println "---------fundPool save time: " + new Date()+ "---------"+" thread id"+t.getName()
				}	
			 }
			}
			/*******************资金池配捐信息处理END*************************/			
			
			//微信发送模板支付凭证
			aipayFlag=true
			 donateurlTemp=donateurl
			 projectTemp=project?.name
			//boolean proof = weiXinService.templet(WeiXinConstants.donate_id , member?.openid , donateurl , project?.name , Float.valueOf(total_fee)+"" , member?.nickname)
			//rest 减去donate_fee    不包含平台管理费
			//判断是否有配捐信息
			/*if(fdonateFlag){
				project.rest -= (Float.valueOf(donate_fee)+Float.valueOf(fdonatemoney)/100)
				project.fDonateSize++
				project.realAmount+=(Float.valueOf(donate_fee)+Float.valueOf(fdonatemoney)/100)
			}else{
				project.rest -= Float.valueOf(donate_fee)
				project.realAmount+=Float.valueOf(donate_fee)
			}
			project.progress = 100-(project.rest/project.amount)*100
	
			//将剩余的钱捐入某个永久项目
			if(project.rest <= 0){
				//TODO
				project.rest = 0
				project.progress = 100
				project.verified = SCFIREConstants.PROJECT_APPROVE_EXECUTE
				//保存系统通知消息
				SystemMessageService.sendSysMessage(SCFIREConstants.SYSTEM_MESSAGE_PROJECT_FUND_SUCCESS_FRONT+project.name+SCFIREConstants.SYSTEM_MESSAGE_PROJECT_FUND_SUCCESS_BACK, project.member)
	
				//筹款成功：推送该项目所有捐赠人，提示用户项目筹款成功，已进入执行阶段，点击详情持续关注项目进展
				Map<String, String> donateUsersOpenid = new HashMap<String, String>()
				Date  date = new Date();
				DateFormat fmt =new SimpleDateFormat("yyyy-MM-dd HH:mm");
				Iterator its = project?.donates?.iterator()
				while(its.hasNext()){
					Donate temp = (Donate)its.next()
					if(temp?.member?.openid){
						donateUsersOpenid.put(temp?.member?.openid , temp?.member?.openid)
					}
				}
	
				weiXinService.sendMassTemplateStatus(WeiXinConstants.service_id, donateUsersOpenid, project?.name+"项目已筹满，您支持的此项目已筹满，我们将尽快支付善款给项目发起人，点击详情持续关注项目最新进展。", fmt.format(date), "项目筹款", "筹款", "成功" , WeiXinConstants.server+"/project/projectDetail?projectid="+project?.id)
				
				//筹款成功：推送该项目发起人，提示用户项目筹款成功，会在5个工作日内打款到您的账上，请点击详情确认收款信息是否准确
				if(project?.member?.openid){
					weiXinService.template_status(WeiXinConstants.service_id, project?.member?.openid, project?.name+"项目已筹满，我们会在5个工作日内支付善款到您的银行卡上，点击详情查看并确认收款银行账号是否准确。", fmt.format(date), "项目筹款", "筹款", "成功" , WeiXinConstants.server+"/user/userAuthInfo")
				}
	
				//筹款成功：发布项目动态，“项目筹款成功”
				feedBackService.insertFeedBack(SCFIREConstants.PROJECT_FEEDBACK_FINISH, project.id+"")
	
			}
			
			//捐赠用户去重
			Set donateMember = new HashSet<>()
			 donateMember.add(member.id)
			 for(Donate d:project.donates){
			 def m = d.member.id
			 donateMember.add(m)
			 }
			//捐赠的用户数累加，按照捐一次累积一次，不做member的去重
			project.donateNum = project.donateNum+1
			
			project.save flush : true*/
			DBCollection projectCollection = db.getCollection("project")
			DBObject queryCondition= new BasicDBObject()
			queryCondition.put("_id",Integer.valueOf(projectid))
			
			float rest = project.rest
			int fDonateSize = project.fDonateSize
			float realAmount = project.realAmount
			float progress = project.progress
			String verified = project.verified
			int donateNum = project.donateNum
			
			if(fdonateFlag){
				project.rest = project.rest - (Float.valueOf(donate_fee)+Float.valueOf(fdonatemoney)/100)
				project.fDonateSize = project.fDonateSize++
				project.realAmount = project.realAmount + (Float.valueOf(donate_fee)+Float.valueOf(fdonatemoney)/100)
			}else{
				project.rest = project.rest - Float.valueOf(donate_fee)
				project.realAmount = project.realAmount+Float.valueOf(donate_fee)
			}
			progress = 100-(project.rest/project.amount)*100
			BigDecimal   b  =   new BigDecimal(progress);
			project.progress=  b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
			
			
			//将剩余的钱捐入某个永久项目
			if(project.rest <= 0){
				//TODO
				project.rest = 0
				project.progress = 100
				project.verified = SCFIREConstants.PROJECT_APPROVE_EXECUTE
				//保存系统通知消息
				Map<String, String> donateUsersOpenid = new HashMap<String, String>()
				Date  date = new Date();
				DateFormat fmt =new SimpleDateFormat("yyyy-MM-dd HH:mm");
				
				
				def Criteriaproject = Donate.createCriteria()
				def dfc = {
					eq("project",project.id)
					order("date", "desc")
					projections {
						distinct ("member")
						   }
				}
				def members = Criteriaproject.listDistinct(dfc);
				for(int id:members){
					def member2 = Member.findById(id)
					donateUsersOpenid.put(member2?.openid , member2?.openid)
				}

				weiXinService.sendMassTemplateStatus(WeiXinConstants.service_id, donateUsersOpenid, project?.name+"项目已筹满，您支持的此项目已筹满，我们将尽快支付善款给项目发起人，点击详情持续关注项目最新进展。", fmt.format(date), "项目筹款", "筹款", "成功" , WeiXinConstants.server+"/project/projectDetail?projectid="+project?.id)
	
	
				//筹款成功：推送该项目发起人，提示用户项目筹款成功，会在5个工作日内打款到您的账上，请点击详情确认收款信息是否准确
				def projectmember
				if(project?.member){
					projectmember= Member.findById(project?.member)
					weiXinService.template_status(WeiXinConstants.service_id, projectmember?.openid, project?.name+"项目已筹满，我们会在5个工作日内支付善款到您的银行卡上，点击详情查看并确认收款银行账号是否准确。", fmt.format(date), "项目筹款", "筹款", "成功" , WeiXinConstants.server+"/user/userAuthInfo")
				}
				
				//筹款成功：发布项目动态，“项目筹款成功”
				feedBackService.insertFeedBack(SCFIREConstants.PROJECT_FEEDBACK_PASS_F+project.name+SCFIREConstants.SYSTEM_MESSAGE_PROJECT_FUND_SUCCESS_BACK, project.id+"","execute")
				
				
				def adminMembers = Member.findAllByPushFlag(true);
				Map<String, String> donateUsersOpenid2 = new HashMap<String, String>()
				for(Member member2:adminMembers){
					donateUsersOpenid2.put(member2?.openid , member2?.nickname)
				}
				weiXinService.sendMassTemplateStatus2(WeiXinConstants.service_id, donateUsersOpenid2, "您好,"+projectmember.nickname+"的项目《"+project.name+"》，已经筹满！", fmt.format(date), "项目筹满", "项目筹满", "成功" , WeiXinConstants.server+"/project/projectDetail?projectid="+project?.id)
			}
			
			/*//捐赠的用户去重
			Set donateMember = new HashSet<>()
			donateMember.add(member.id)
			for(Donate d:project.donates){
			def m = d.member.id
			donateMember.add(m)
			}
			project.donateNum = donateMember.size()*/
		   //捐赠的用户数累加，按照捐一次累积一次，不做member的去重
		   project.donateNum++
		   BasicDBObject updateParameter =new BasicDBObject().append("\$set",new BasicDBObject().append("rest", project.rest)
																.append("fDonateSize", project.fDonateSize)
																.append("realAmount", project.realAmount)
																.append("progress", project.progress)
																.append("verified", project.verified)
																.append("donateNum", project.donateNum)
																)												
		  projectCollection.update(queryCondition, updateParameter,true,true)
			
			
		}catch(Exception e){
			println "alipaycallBack catch exception "+e.getMessage()
			return false
		}
		
		println "---------End time: " + new Date()+ "---------"+" thread id"+t.getName()
		
		
	  }		  
	  if(aipayFlag){
		  Thread t = Thread.currentThread()
		 println "---------start weixin time: " + new Date()+ "---------"+" thread id："+t.getName()
		  Member member = Member.findById(memberid)
		  boolean proof = weiXinService.templet(WeiXinConstants.donate_id , member?.openid , donateurlTemp ,projectTemp , Float.valueOf(total_fee)+"" , member?.nickname)
		  println "send stats ailipay : "+ proof
		  aipayFlag=false
		  donateurlTemp=""
		  projectTemp=""
		  println "---------end weixin time: " + new Date()+ "---------"+" thread id："+t.getName()
	  }
	  
	  return true
	 }
				  
			
				  
				  @Transactional(propagation = Propagation.REQUIRED)
				  def checkCallBack(String memberId,
							   String projectId,
							   float donate_fee,
							   float operate_fee,
							   String subprojectid,
							   String total_fee,
							   String out_trade_no,
							   String openid,
							   String transaction_id,
							   boolean checked,
							   String attach,
							   String donateNoNew,
							    String type,
								String date1){
							   boolean weixinflag = false
							   def donateurlTemp;
							   def projectTemp
							  
							  if(forLock.get(projectId)==null){
								  forLock.put(projectId, new Object[0])
							  }
				   synchronized(forLock.get(projectId)) {
		 
		 Thread t = Thread.currentThread()
		 println "---------Start time: " + new Date()+ "---------"+" thread id"+t.getName()
						 
		try{
			//判断是否已经有捐赠记录
			Donate donate = Donate.findByOut_trade_no(out_trade_no)
			if(donate){
				return true
			}
			
			Member member = Member.findById(memberId)
			Project project = Project.findById(projectId)
			String donateurl = ""
			SubProject subproject
			//加载mongodb
			def db = mongo.getDB(grailsApplication.config.grails.mongo.databaseName)
			
			//若是一起捐 则保存信息到subproject
			if(!subprojectid.equals("-1")){
				subproject = SubProject.findById(subprojectid)
				subproject.subrest -= Float.valueOf(donate_fee)
				subproject.subdonate += Float.valueOf(donate_fee)
				float subprogress = 100-(subproject.subrest/subproject.subamount)*100
				BigDecimal   b  =   new BigDecimal(subprogress);
				subproject.subprogress=  b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
				//4.金额计算，subProject rest计算，
				if(subproject.subrest <= 0){
					subproject.subrest = 0
					subproject.subprogress = 100
				}
				subproject.subdonateSize++
				
				FRuler fRuler = FRuler.findByProjectAndStatus(project,"true")
				int fdonatemoney = 0
				float regular = 0
				if(fRuler != null){
					FundPool fundPool = fRuler.fundPool
					BigDecimal bd = new BigDecimal(Float.toString(donate_fee))
					bd=bd*100;
					int donatemoney = bd.intValue();
					int bandfund = fRuler.bandfund
					int donatefund = fRuler.donatefund
					String fRegular = fRuler.regular
					String[] fRs = fRegular.split(":")
					regular = (Float.valueOf(fRs[1])/Float.valueOf(fRs[0])) //保留两位
					
					//计算可用金额 = 绑定配捐金额-实际已配捐金额
					int restfund = bandfund - donatefund
					if(restfund > 0){
						//可用金额根据配捐规则大于此次要配捐的金额,则进行配捐
						if(restfund >= donatemoney*regular){
							fdonatemoney = donatemoney*regular
						}else{
							//最后剩余的全部进行配捐
							fdonatemoney = restfund
						}
					}
				}
				subproject.subfdonate+=fdonatemoney
				DBCollection projectCollection = db.getCollection("subProject")
				DBObject queryCondition= new BasicDBObject()
				queryCondition.put("_id",Integer.valueOf(subprojectid))
				BasicDBObject updateParameter =new BasicDBObject().append("\$set",new BasicDBObject().append("subrest", subproject.subrest)
					.append("subdonate", subproject.subdonate)
					.append("subprogress", subproject.subprogress)
					.append("subdonateSize", subproject.subdonateSize)
					.append("subfdonate", subproject.subfdonate)
					)
				
				projectCollection.update(queryCondition, updateParameter,true,true)		
				//subproject.save flush : true
				println "---------save subproject time: " + new Date()+ "---------"+" thread id"+t.getName()
				
			}
			
			
			long timestap = System.currentTimeMillis()/1000
			
			//捐赠信息
			donate = new Donate()
			donate.donateNo = UUID.randomUUID()
			donate.donateNoNew = donateNoNew
			donate.money = Float.valueOf(total_fee)
	
			donate.donate_fee = donate_fee
			donate.operate_fee = operate_fee
			donate.operate_fee_status = checked
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
			donate.date = sdf.parse(date1);
			donate.status = true
			donate.member = member.id
			donate.project = project.id
			//若是一起捐 保存捐赠信息到donate
			if(!subprojectid.equals("-1")) donate.subProject = subproject.id
			donate.out_trade_no = out_trade_no
			donate.openid = openid
			donate.transaction_id = transaction_id
			donate.attach = attach
			donate.type = type
			//donate.save flush : true
			
			DBCollection projectCollections = db.getCollection("donate")
			BasicDBObject doc_info = new BasicDBObject();
			
			doc_info.put("donateNo", donate?.donateNo);
			doc_info.put("donateNoNew", donate?.donateNoNew);
			doc_info.put("money",  String.valueOf(donate.money));
			doc_info.put("donate_fee", String.valueOf(donate.donate_fee));
			doc_info.put("operate_fee", String.valueOf(donate.operate_fee));
			doc_info.put("operate_fee_status", donate?.operate_fee_status);
			doc_info.put("date", donate.date);
			doc_info.put("status", donate.status);
			doc_info.put("member", member?.id);
			doc_info.put("project", project?.id);
			if(!subprojectid.equals("-1")) {
				doc_info.put("subProject", subproject.id);
			}
			doc_info.put("out_trade_no", donate.out_trade_no);
			doc_info.put("openid", donate.openid);
			doc_info.put("transaction_id", donate.transaction_id);
			doc_info.put("attach", donate.attach);
			doc_info.put("type", donate.type);
			Donate d= Donate.last()
			doc_info.put("_id", d.id+1);
			try {
				projectCollections.insert(doc_info);
			} catch (Exception e) {
			Donate d1= Donate.last()
			println "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" +d1.id+1
			doc_info.put("_id", d1.id+1);
			projectCollections.insert(doc_info);
			}
			println "---------save donate time: " + new Date()+ "---------"+" thread id"+t.getName()
			
			//手动查找donate.id
			Donate donate2 = Donate.findByOut_trade_no(out_trade_no)
			donateurl = SCFIREConstants.PROJECT_DONATE_ELECTRONIC_INFO+donate2.id
			//donateurl = "http://www.huodui.org/scfire/user/modifyMoblie"
			
			/*******************资金池配捐信息处理START*************************/
			//配捐信息获取
			FRuler fRuler = FRuler.findByProjectAndStatus(project,"true")
			//配捐标识
			boolean fdonateFlag = false
			//配捐金额
			int fdonatemoney = 0
			
			float regular = 0
			//如果项目有绑定资金池
			if(fRuler != null){
				FundPool fundPool = fRuler.fundPool
				if(forLockfundPool.get(String.valueOf(fundPool.id))==null){
					forLockfundPool.put(String.valueOf(fundPool.id), new Object[0])
				}
				synchronized(forLockfundPool.get(String.valueOf(fundPool.id))){
				BigDecimal bd = new BigDecimal(Float.toString(donate_fee))
				bd=bd*100;
				int donatemoney = bd.intValue();
				println "-----1----"+donatemoney+"---------"
				int bandfund = fRuler.bandfund
				int donatefund = fRuler.donatefund
				String fRegular = fRuler.regular
				String[] fRs = fRegular.split(":")									
				regular = (Float.valueOf(fRs[1])/Float.valueOf(fRs[0])) //保留两位				
				
				//计算可用金额 = 绑定配捐金额-实际已配捐金额
				int restfund = bandfund - donatefund			
				if(restfund > 0){
					//可用金额根据配捐规则大于此次要配捐的金额,则进行配捐
					if(restfund >= donatemoney*regular){
						fdonatemoney = donatemoney*regular
						fRuler.donatefund += fdonatemoney
					}else{
						//最后剩余的全部进行配捐
						fdonatemoney = restfund
						fRuler.donatefund = bandfund	
					}
					
					println "---2------"+fdonatemoney+"---------"
					//添加配捐信息
					Donate donate1 = Donate.findByOut_trade_no(out_trade_no)
					FDonate fDonate = new FDonate()
					fDonate.donate_fee = fdonatemoney
					fDonate.status = "true"
					fDonate.date = new Date()
					fDonate.fundPool = fundPool.id
					fDonate.project = project.id
					fDonate.member = member.id
					fDonate.donate = donate1.id	
					DBCollection projectCollections2 = db.getCollection("FDonate")
					BasicDBObject doc_info2 = new BasicDBObject();
					doc_info2.put("donate_fee", fDonate.donate_fee);
					doc_info2.put("status",fDonate.status);
					doc_info2.put("date", fDonate.date);
					doc_info2.put("fundPool",fundPool?.id);
					doc_info2.put("project", project?.id);
					doc_info2.put("member", member?.id);
					doc_info2.put("donate",donate1?.id);
					doc_info2.put("version",0);
					FDonate fd= FDonate.last()
					doc_info2.put("_id", fd.id+1);
					try {
						projectCollections2.insert(doc_info2);
					} catch (Exception e) {
						FDonate fd1= FDonate.last()
						doc_info2.put("_id", fd1.id+1);
						projectCollections2.insert(doc_info2);
					}
					
					//更新配捐规则中实际配捐金额信息
					fRuler.save flush:true
					
					//更新资金池中实际已经配捐金额信息
					fundPool.donateActual += fdonatemoney
					DBCollection projectCollection = db.getCollection("fundPool")
					DBObject queryCondition= new BasicDBObject()
					queryCondition.put("_id",fundPool.id)
					BasicDBObject updateParameter =new BasicDBObject().append("\$set",new BasicDBObject().append("donateActual", fundPool.donateActual))
					projectCollection.update(queryCondition, updateParameter,true,true)
					//fundPool.save flush:true
					println "---------fundPool save " + new Date()+ "---------"+" thread id"+t.getName()
					fdonateFlag = true
				}
			 }	
			}
			println "---------save fundpool: " + new Date()+ "---------"+" thread id"+t.getName()
			/*******************资金池配捐信息处理END*************************/
			DBCollection projectCollection = db.getCollection("project")
			DBObject queryCondition= new BasicDBObject()
			queryCondition.put("_id",Integer.valueOf(projectId))
			
			float rest = project.rest
			int fDonateSize = project.fDonateSize
			float realAmount = project.realAmount
			float progress = project.progress
			String verified = project.verified
			int donateNum = project.donateNum
			if(fdonateFlag){
				project.rest = project.rest - (Float.valueOf(donate_fee)+Float.valueOf(fdonatemoney)/100)
				project.fDonateSize = project.fDonateSize++
				project.realAmount = project.realAmount + (Float.valueOf(donate_fee)+Float.valueOf(fdonatemoney)/100)
			}else{
				project.rest = project.rest - Float.valueOf(donate_fee)
				project.realAmount = project.realAmount+Float.valueOf(donate_fee)
			}
			
			progress = 100-(project.rest/project.amount)*100
			
			BigDecimal   b  =   new BigDecimal(progress);
			project.progress=  b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
			
			//将剩余的钱捐入某个永久项目
			if(project.rest <= 0){
				//TODO
				project.rest = 0
				project.progress = 100
				project.verified = SCFIREConstants.PROJECT_APPROVE_EXECUTE
				//保存系统通知消息
				SystemMessageService.sendSysMessage(SCFIREConstants.SYSTEM_MESSAGE_PROJECT_FUND_SUCCESS_FRONT+project.name+SCFIREConstants.SYSTEM_MESSAGE_PROJECT_FUND_SUCCESS_BACK, project.member);
	
				//筹款成功：推送该项目所有捐赠人，提示用户项目筹款成功，已进入执行阶段，点击详情持续关注项目进展
				Map<String, String> donateUsersOpenid = new HashMap<String, String>()
				Date  date = new Date();
				DateFormat fmt =new SimpleDateFormat("yyyy-MM-dd HH:mm");
				
				
				def Criteriaproject = Donate.createCriteria()
				def dfc = {
					eq("project",project.id)
					order("date", "desc")
					projections {
						distinct ("member")
						   }
				}
				def members = Criteriaproject.listDistinct(dfc);
				for(int id:members){
					def member2 = Member.findById(id)
					donateUsersOpenid.put(member2?.openid , member2?.openid)
				}
				weiXinService.sendMassTemplateStatus(WeiXinConstants.service_id, donateUsersOpenid, project?.name+"项目已筹满，您支持的此项目已筹满，我们将尽快支付善款给项目发起人，点击详情持续关注项目最新进展。", fmt.format(date), "项目筹款", "筹款", "成功" , WeiXinConstants.server+"/project/projectDetail?projectid="+project?.id)
				//筹款成功：推送该项目发起人，提示用户项目筹款成功，会在5个工作日内打款到您的账上，请点击详情确认收款信息是否准确
				def projectmember
				if(project?.member){
					projectmember= Member.findById(project?.member)
					weiXinService.template_status(WeiXinConstants.service_id, projectmember?.openid, project?.name+"项目已筹满，我们会在5个工作日内支付善款到您的银行卡上，点击详情查看并确认收款银行账号是否准确。", fmt.format(date), "项目筹款", "筹款", "成功" , WeiXinConstants.server+"/user/userAuthInfo")
				}
				//筹款成功：发布项目动态，“项目筹款成功”
				feedBackService.insertFeedBack(SCFIREConstants.PROJECT_FEEDBACK_PASS_F+project.name+SCFIREConstants.SYSTEM_MESSAGE_PROJECT_FUND_SUCCESS_BACK, project.id+"","execute")
				def adminMembers = Member.findAllByPushFlag(true);
				Map<String, String> donateUsersOpenid2 = new HashMap<String, String>()
				for(Member member2:adminMembers){
					donateUsersOpenid2.put(member2?.openid , member2?.nickname)
				}
				weiXinService.sendMassTemplateStatus2(WeiXinConstants.service_id, donateUsersOpenid2, "您好,"+projectmember.nickname+"的项目《"+project.name+"》，已经筹满！", fmt.format(date), "项目筹满", "项目筹满", "成功" , WeiXinConstants.server+"/project/projectDetail?projectid="+project?.id)
			}
		    project.donateNum++
		   BasicDBObject updateParameter =new BasicDBObject().append("\$set",new BasicDBObject().append("rest", project.rest)
																.append("fDonateSize", project.fDonateSize)
																.append("realAmount", project.realAmount)
																.append("progress", project.progress)
																.append("verified", project.verified)
																.append("donateNum", project.donateNum)
																)									
		  projectCollection.update(queryCondition, updateParameter,true,true)
		  println "---------save project: " + new Date()+ "---------"+" thread id"+t.getName()
		  return true
		}catch(Exception e){
			println "weixincallBack catch exception "+e.getMessage()
			println "sfafdasdfasdfasdfasdfasdf"+"111111111111111111111111111"
			return false
		}
	 }
}
							   
							   
							   
							   

}
